/*
 * Created on 2007-10-21
 *
 * TODO
 */
package jacky.lanlan.song.extension.struts;

import java.lang.reflect.Method;

/**
 * 路径映射器。
 * <p>
 * 映射URL到Struts Action的执行方法。 <p style="color:red;font-weight:bolder">
 * 注意：如果使用Spring来管理Aciton，则需要在AnnotationConfigPlugIn和ConfigStrutsActionBean中
 * 同时指定相同的Mapper，否则URL将不能映射到Spring管理的Action。
 * </p>
 * 
 * @author Jacky.Song
 * @see jacky.lanlan.song.extension.struts.AnnotationConfigPlugIn
 * @see jacky.lanlan.song.extension.spring.struts.ConfigStrutsActionBean
 */
public interface URLMethodMapper {
	
	/**
	 * 提供自定义的Action的执行方法到URL的映射关系。
	 * 
	 * @param executionMethod
	 *          String Action的执行方法
	 * @param basePackage
	 *          映射该方法访问路径的 basePackage，在配置插件时设置的
	 * @return 对应该方法的URL(相对于Web应用的根路径)
	 */
	public String mapMethodToURL(Method executionMethod,String basePackage);
	
	/**
	 * 默认映射器，提供Ruby-like式的映射规则。 <p style="color:green;font-weight:bolder">
	 * 使用默认映射器，必须在AnnotationConfigPlugIn和ConfigStrutsActionBean中设置basePackage 属性。 </p> <p/> 映射规则如下: <p
	 * style="color:red;font-weight:bolder"> 以给定的Action类所在包路径(basePackage)开始，划分Action的子目录。 <br>
	 * 比如有aaa.bbb.Action1和aaa.bbb.ccc.Action2两个Action，在AnnotationConfigPlugIn
	 * 里设置的basePackage为aaa.bbb，则截去aaa.bbb，然后执行以下规则: </p> <ul style="color:blue;font-weight:bolder">
	 * <li>
	 * 如果Action类名以<em>Action</em>结尾，<em>Action</em>被删除</li> <li>
	 * 方法名：所有大写字母前面加'_'，然后转换为小写</li> <li>
	 * 剩下的包名作为子目录路径，'.'转换为'/'</li> </ul> <p style="color:red;font-weight:bolder"> 即： <br/>
	 * aaa.bbb.MyAction.myMethod ——> /My!my_method.do <br/> aaa.bbb.ccc.MyAction.myMethod ——>
	 * /ccc/My!my_method.do
	 */
	public URLMethodMapper DEFAULT =new URLMethodMapper() {
		
		/**
		 * 用来标识默认URL映射中 Action 类名和执行方法的分割符。
		 */
		public static final String URL_SEPARATER="!";
		
		public String mapMethodToURL(Method executionMethod,String basePackage) {
			String methodName = executionMethod.getName();// 方法名
			String className = executionMethod.getDeclaringClass().getName();// Bean类名
		
			String path = className.replace(basePackage, "").// 取basePackage后面的路径
					replace('.', '/');// '.'转换为'/'
		
			return path.replaceAll("Action$", "") + // 如果以Action结尾，删除Action
					URL_SEPARATER + // SEPARATER后面跟方法名
					methodName.replaceAll("([A-Z])", "_$1").toLowerCase();// 适当转换方法名
		}
		
	};
	
}
